# -*- coding: utf-8 -*-
import hashlib
import json
from collections import OrderedDict

import requests
from django.conf import settings

from async import async_job
from common.cache import redis_cache
from common.order import db as order_db
from common.order.db import get_pay, add_pay_success
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError

_LOGGER = track_logging.getLogger(__name__)

_GATEWAY = 'https://pay.ipay.kim/cashier/Home'
_QUERY_GATEWAY = 'https://pay.ipay.kim/pay/queryorder'
#  接Loki的银联合 qq钱包

APP_CONF = {
    '50463': {
        'API_KEY': '7582f7831a9b42218b094c591cb4c8c7',
        'gateway': 'https://pay.ipay.kim/cashier/Home',
        'query_gateway': 'https://pay.ipay.kim/pay/queryorder',
    },
    '50581': {  # 支付宝和qqwap dwc
        'API_KEY': '9e2fe2508e0743c3aabceedd93bece33',
        'gateway': 'http://ipay.ttpay.net.cn/cashier/Home',
        'query_gateway': 'http://ipay.ttpay.net.cn/pay/queryorder',
    },
    '1000090': {  # dwc 久易支付 支付宝3.5%（80---3000）.t0结算。
        'API_KEY': '578797aa3f144ad899ddca694710bd69',
        'gateway': 'https://vip.dddyn.com/cashier/Home',
        'query_gateway': 'https://vip.dddyn.com/pay/queryorder',
    },
    '1000019': {  # dwc 合通 支付宝：3.3%（10---3000），do结算。
        'API_KEY': '2fa3a1df0568429497344d6eacb38103',
        'gateway': 'http://116.62.97.93/cashier/Home',
        'query_gateway': 'http://116.62.97.93/pay/queryorder',
    },
    '1000165': {  # dwc 久易支付 支付宝费率是4%（100，200，300，400----5000整百充值）d0结算
        'API_KEY': '8ddabba3551f442e80761340318fa18d',
        'gateway': 'https://vip.dddyn.com/cashier/Home',
        'query_gateway': 'https://vip.dddyn.com/pay/queryorder',
    },
    '1000043': {  # witch 合通 支付宝3.5%（10---2000）d0结算。
        'API_KEY': 'bf212cc08306486394d2c935179b2bdc',
        'gateway': 'http://47.99.2.204/cashier/Home',
        'query_gateway': 'http://47.99.2.204/pay/queryorder',
    },
    '1000171': {  # witch 合付通 支付宝2.9%（100---10000）d0结算。
        'API_KEY': '8688b47ab0704747bd03a9edb4b0eba9',
        'gateway': 'http://47.99.2.204/cashier/Home',
        'query_gateway': 'http://47.99.2.204/pay/queryorder',
    },
    '1000169': {  # zs 合付通 支付宝2.9%（100---10000）d0结算。
        'API_KEY': '898af866fbb24eefa2d648d9d689c600',
        'gateway': 'http://47.99.2.204/cashier/Home',
        'query_gateway': 'http://47.99.2.204/pay/queryorder',
    },
}


def _get_gateway(mch_id):
    return APP_CONF[mch_id]['gateway']


def _get_query_gateway(mch_id):
    return APP_CONF[mch_id]['query_gateway']


def _get_api_key(mch_id):
    return APP_CONF[mch_id]['API_KEY']


def _gen_md5_sign(s):
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    sign = m.hexdigest()
    return sign


# Md5(mch_id + out_trade_no + callback_url + notify_url + total_fee + service + way+ format + 商户密钥)
def generate_sign(d, key):
    s = d['mch_id'] + d['out_trade_no'] + d['callback_url'] + d['notify_url'] + d['total_fee'] + d['service'] + d[
        'way'] + d['format']
    s += key
    return _gen_md5_sign(s)


# Md5(mch_id + out_trade_no + transaction_id + nonce_str + 商户密钥)
def gen_query_sign(d, key):
    s = d['mch_id'] + d['out_trade_no'] + d['nonce_str'] + key
    return _gen_md5_sign(s)


# mch_id + time_end + out_trade_no + ordernumber + transtypeid + transaction_id + total_fee + service + way + result_code + 密钥
# Md5(mch_id + device_info+ attach + time_end + out_trade_no + ordernumber + transtypeid + transaction_id + total_fee + service+ way + result_code + 密钥)
def gen_notify_sign(d, key):
    s = d['mch_id'] + d.get('device_info', '') + d.get('attach', '') + d['time_end'] + d['out_trade_no'] + d[
        'ordernumber'] + d[
            'transtypeid'] + d['transaction_id'] + d['total_fee'] + d['service'] + d['way'] + d['result_code'] + key
    return _gen_md5_sign(s)


def verify_notify_sign(data, key):
    calculated_sign = gen_notify_sign(data, key)
    sign = data['sign']
    if sign.upper() != calculated_sign.upper():
        _LOGGER.info("yjhpay sign: %s, calculated sign: %s", sign, calculated_sign)
        raise ParamError('sign not pass, data: %s' % data)


def _get_device_ip(info):
    try:
        extra = json.loads(info['extra'])
    except:
        extra = {}
    user_info = extra.get('user_info', {})
    return user_info.get('device_ip') or '127.0.0.1'


# wx:微信
# al:支付宝
# qq:qq钱包
# jd:京东
# wy:网银支付
# kj:快捷支付
# yl:银联二维码
def _get_pay_type(service):
    if service == 'wxpay':
        payType = 'wx'
    elif service == 'alipay':
        payType = 'al'
    elif service == 'qq':
        payType = 'qq'
    elif service == 'jd':
        payType = 'jd'
    elif service == 'wy':
        payType = 'wy'
    elif service == 'quickbank':
        payType = 'kj'
    elif service == 'yl':
        payType = 'yl'
    else:
        payType = 'qq'
    return payType


def _build_form(params, gateway):
    html = u"<head><title>loading...</title></head><form id='submit' name='submit' action='" + gateway + "' method='get'>"
    for k, v in params.items():
        html += "<input type='hidden' name='%s' value='%s'/>" % (k, v)
    html += "</form>"
    html += "<script>document.forms['submit'].submit();</script>"
    return html


def create_charge(pay, pay_amount, info):
    service = info.get('service')
    app_id = info['app_id']
    api_key = _get_api_key(app_id)
    parameter_dict = OrderedDict((
        ('mch_id', app_id),
        ('out_trade_no', str(pay.id)),
        ('body', 'charge'),
        # ('sub_openid', str(pay.id)),
        ('callback_url', '{}/pay/api/{}/yjhpay/{}/'.format(settings.NOTIFY_PREFIX, settings.RETURN_PATH, pay.id)),
        ('notify_url', '{}/pay/api/{}/yjhpay/{}'.format(settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
        ('total_fee', str(pay_amount)),
        ('service', _get_pay_type(service)),
        ('way', 'wap'),
        # ('Appid', 'wap'),
        ('format', 'xml'),
        ('mch_create_ip', _get_device_ip(info)),
    ))
    parameter_dict['sign'] = generate_sign(parameter_dict, api_key)
    _LOGGER.info("yjhpay create data : %s", parameter_dict)
    html = _build_form(parameter_dict, _get_gateway(app_id))
    cache_id = redis_cache.save_html(pay.id, html)
    return {'charge_info': settings.PAY_CACHE_URL + cache_id}


# SUCCESS
def check_notify_sign(request, app_id):
    key = _get_api_key(app_id)
    data = dict(request.GET.iteritems())
    _LOGGER.info("yjhpay notify data: %s", data)
    verify_notify_sign(data, key)
    pay_id = data['out_trade_no']
    if not pay_id:
        _LOGGER.error("fatal error, pay object not exists, data: %s" % data)
        raise ParamError('yjhpay event does not contain valid pay ID')

    pay = get_pay(pay_id)
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    mch_id = pay.mch_id
    trade_status = int(data['result_code'])
    trade_no = data['transaction_id']
    total_fee = float(data['total_fee'])

    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee
    }

    from common.channel.pay import check_channel_order
    check_channel_order(pay_id, total_fee, app_id)

    # 0为成功 其余为失败
    if trade_status == 0:
        _LOGGER.info('yjhpay check order success, user_id:%s pay_id:%s' % (mch_id, pay_id))
        add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
        # async notify
        async_job.notify_mch(pay_id)


def query_charge(pay_order, app_id):
    ''' 查询订单 '''
    # prepare param
    pay_id = pay_order.id
    api_key = _get_api_key(app_id)
    parameter_dict = OrderedDict((
        ('mch_id', app_id),
        ('out_trade_no', str(pay_id)),
        ('nonce_str', 'charge'),
    ))
    parameter_dict['sign'] = gen_query_sign(parameter_dict, api_key)
    _LOGGER.info('yjhpay query data: %s', parameter_dict)
    response = requests.get(_get_query_gateway(app_id), params=parameter_dict)
    _LOGGER.info('yjhpay query response: %s', response.text)
    if response.status_code == 200:
        # response text is a pure html text
        data = json.loads(response.text)
        trade_status = str(data['trade_state'])
        trade_no = str(data['transaction_id'])
        total_fee = float(data['total_fee'])

        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee
        }

        if trade_status == 'SUCCESS':
            _LOGGER.info('yjhpay query order success, user_id:%s pay_id:%s' % (pay_order.mch_id, pay_id))
            order_db.add_pay_success(pay_order.mch_id, pay_order.id,
                                     total_fee, trade_no, extend)

            async_job.notify_mch(pay_order.id)
            print("order process successfully. %s" % pay_order.id)
    else:
        _LOGGER.warn('yjhpay data error, status_code: %s', response.status_code)
